﻿namespace Devonline.Security;

/// <summary>
/// 密钥和数据组成的数据结构, 由 密钥和数据 两部分组成
/// 密钥部分可以是 KeyIV.Value 或者是一个密钥的编号
/// 数据部分是数据经密钥加密后的密文
/// </summary>
public class KeyData
{
    /// <summary>
    /// 加密方式
    /// </summary>
    public DataEncryptionMode EncryptionMode { get; private set; }
    /// <summary>
    /// 对称加密算法 Key 的长度, AES 256 CBC 模式下默认 32
    /// </summary>
    public int KeySize { get; private set; }
    /// <summary>
    /// 数据部分长度
    /// </summary>
    public int DataSize { get; private set; }
    /// <summary>
    /// 密钥部分-密钥编号/密钥密文
    /// </summary>
    public byte[] Key { get; private set; }
    /// <summary>
    /// 数据部分-密文
    /// </summary>
    public byte[] Data { get; private set; }
    /// <summary>
    /// 对称算法密钥组成: KeySize(4)+IVSize(4)+Key+IV
    /// </summary>
    public byte[] Value { get; private set; }
    /// <summary>
    /// 密钥编号
    /// </summary>
    public long KeyId { get; private set; }
    /// <summary>
    /// 当前数据中包含的密钥信息
    /// </summary>
    public KeyIV? KeyIV { get; private set; }

    /// <summary>
    /// 使用 key 和 data 初始化密钥和数据
    /// </summary>
    /// <param name="key">密钥部分</param>
    /// <param name="data">数据部分密文</param>
    protected KeyData(byte[] key, byte[] data)
    {
        Key = key;
        Data = data;
        KeySize = Key.Length;
        DataSize = Data.Length;
        Value = new byte[KeySize + DataSize + AppSettings.UNIT_EIGHT];
        var bytes = BitConverter.GetBytes(KeySize);
        Array.Copy(bytes, AppSettings.UNIT_ZERO, Value, AppSettings.UNIT_ZERO, AppSettings.UNIT_FOUR);
        bytes = BitConverter.GetBytes(DataSize);
        Array.Copy(bytes, AppSettings.UNIT_ZERO, Value, AppSettings.UNIT_FOUR, AppSettings.UNIT_FOUR);
        Array.Copy(Key, AppSettings.UNIT_ZERO, Value, AppSettings.UNIT_EIGHT, KeySize);
        Array.Copy(Data, AppSettings.UNIT_ZERO, Value, AppSettings.UNIT_EIGHT + KeySize, DataSize);
    }
    /// <summary>
    /// 使用 密钥编号 和 data 初始化密钥和数据
    /// 此模式下使用密钥的编号, 长度固定为 8 字节,  此处使用 32 位数字表示密钥编号长度
    /// </summary>
    /// <param name="keyId">密钥编号</param>
    /// <param name="data">数据部分密文</param>
    public KeyData(long keyId, byte[] data) : this(BitConverter.GetBytes(keyId), data)
    {
        KeyId = keyId;
        EncryptionMode = DataEncryptionMode.KeyId;
    }
    /// <summary>
    /// 以 KeyIV 和 data 方式初始化密钥和数据对象
    /// </summary>
    /// <param name="keyIV">密钥部分, 完整的 KeyIV 对象</param>
    /// <param name="data">数据部分密文</param>
    public KeyData(KeyIV keyIV, byte[] data) : this(keyIV.Value, data)
    {
        KeyIV = keyIV;
        KeyId = keyIV.Id;
        EncryptionMode = DataEncryptionMode.KeyIV;
    }

    /// <summary>
    /// 使用结果结构密钥和数据
    /// </summary>
    /// <param name="value">完整的密钥+数据结构</param>
    public KeyData(byte[] value)
    {
        Value = value;
        KeySize = BitConverter.ToInt32(value);
        DataSize = BitConverter.ToInt32(value, AppSettings.UNIT_FOUR);
        Key = new byte[KeySize];
        Data = new byte[DataSize];
        Array.Copy(Value, AppSettings.UNIT_EIGHT, Key, AppSettings.UNIT_ZERO, KeySize);
        Array.Copy(Value, AppSettings.UNIT_EIGHT + KeySize, Data, AppSettings.UNIT_ZERO, DataSize);

        if (KeySize == AppSettings.UNIT_EIGHT)
        {
            EncryptionMode = DataEncryptionMode.KeyId;
            KeyId = BitConverter.ToInt64(Key);
        }
        else
        {
            EncryptionMode = DataEncryptionMode.KeyIV;
            KeyIV = new KeyIV(Key);
            KeyId = KeyIV.Id;
        }
    }
}